/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package tools;

import com.openbrew.openbrewrf.InvPSOLines;
import com.openbrew.openbrewrf.InvSalesLines;
import com.openbrew.openbrewrf.PSOLines;
import com.openbrew.openbrewrf.PendingSO;
import com.openbrew.openbrewrf.Sales;
import com.openbrew.openbrewrf.SalesOrder;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;

/**
 *
 * @author dchapman
 */
public class SaleTools {
    /***************************************************************************
     * Sale Insertion Actions.
     **************************************************************************/
    /***************************************************************************
     * Do a supply removal without adjusting allocation
     * @param en - Entity Manager
     * @param sale - Sale being inserted.
     * @param allocated - is this an allocated sale?
     **************************************************************************/
    public void doSaleInsertionActions(final EntityManager en
            , final Sales sale, final boolean allocated){
        //If the keg ID is set we need to update the keg with the customer information.
        if(sale.getKegID()!=0){
            final KegTools kt = new KegTools();
            kt.doSetKegFromSale(en, sale);
        } else {
            //Remove Keg to POSSale
            POSVolumeModifier vm = new POSVolumeModifier();
            vm.doVolumeAddition(en, sale);
        }
        final InventoryModifiers im = new InventoryModifiers();
        if(allocated){
            im.doFGIRemovalWithAllocation(en, sale.getSalesFGIID().getFgiid(), sale.getSalesFGIQty());
        } else {
            if(sale.getSalesFGIID().getFGIPackageID().isServingVessel()){
                im.doFGIServingTankRemovalWithoutAllocation(en, sale.getSalesFGIID().getFgiid(), sale.getServingTankVolume());
            } else {
                im.doFGIRemovalWithoutAllocation(en, sale.getSalesFGIID().getFgiid(), sale.getSalesFGIQty());
            }
        }
    }
    /***************************************************************************
     * Do a supply removal without adjusting allocation
     * @param en - Entity Manager
     * @param sale - Sale being inserted.
     * @param allocated - is this an allocated sale?
     **************************************************************************/
    public void doInvSaleInsertionActions(final EntityManager en
            , final InvSalesLines sale, final boolean allocated){
        final InventoryModifiers im = new InventoryModifiers();
        if(allocated){
            im.doSupplyRemovalWithAllocation(en
                    , (int)sale.getInvSaleSupplyID().getSupID(), sale.getInvSaleQty());
        } else {
            im.doSupplyRemovalWithoutAllocation(en
                    , (int)sale.getInvSaleSupplyID().getSupID(), sale.getInvSaleQty());
        }
    }
    
    /***************************************************************************
     * Do a supply removal without adjusting allocation
     * @param en - Entity Manager
     * @param so - SaleOrder being inserted.
     * @param allocated - is this an allocated sale?
     * @return salesOrder update Sales Order
     **************************************************************************/
    public SalesOrder doSaleOrderInsertionActions(final EntityManager en
            , final SalesOrder so, final boolean allocated){
        if(so.getSalesCollection()!=null){
            List<Sales> newSales = new ArrayList<Sales>();
            for(final Sales saleLine : so.getSalesCollection()){
                newSales.add(createSaleLine(en, saleLine));
                doSaleInsertionActions(en, saleLine, allocated);
            }
            so.setSalesCollection(newSales);
        }
        if(so.getInvSalesLinesCollection()!=null){
            List<InvSalesLines> newSales = new ArrayList<InvSalesLines>();
            for(final InvSalesLines saleLine : so.getInvSalesLinesCollection()){
                newSales.add(createInvSaleLine(en, saleLine));
                doInvSaleInsertionActions(en, saleLine, allocated);
            }
            so.setInvSalesLinesCollection(newSales);
        }
        return so;
    }
    
    private Sales createSaleLine(final EntityManager en, final Sales sale){
        en.persist(sale);
        en.flush();
        en.refresh(sale);
        return sale;
    }
    
    private InvSalesLines createInvSaleLine(final EntityManager en, final InvSalesLines sale){
        en.persist(sale);
        en.flush();
        en.refresh(sale);
        return sale;
    }
    
    /***************************************************************************
     * Pending Sale Tools.
     **************************************************************************/
    /***************************************************************************
     * FGI Allocation Update Per Pending SO
     * @param en
     * @param newPSO
     **************************************************************************/
    public void fgiAllocationUpdatePerPSO(final EntityManager en, final PendingSO newPSO){
        final PendingSO currentPSO = getPSOFromID(en, newPSO.getPsoid());
        final InventoryModifiers im = new InventoryModifiers();
        
        //Set lists so there are no null values.
        List<PSOLines> currentLines = new ArrayList<PSOLines>();
        List<PSOLines> newLines = new ArrayList<PSOLines>();
        if(currentPSO.getPSOLinesCollection()!=null){
            currentLines = currentPSO.getPSOLinesCollection();
        }
        if(newPSO.getPSOLinesCollection()!=null){
            newLines = newPSO.getPSOLinesCollection();
        }
        
        for(final PSOLines newLine : newLines){
            if(newLine.getPSOID()==null || newLine.getPSOID()==0){
                //This is a new line update allocations accordingly.
                im.doFGIAllocationAddition(en, newLine.getPSOFGI().getFgiid()
                            , newLine.getPSOQty());
            } else {
                for(final PSOLines currentLine : currentLines){
                    if(newLine.getPSOID()==currentLine.getPSOID()){
                        if(newLine.getPSOQty() > currentLine.getPSOQty()){
                            im.doFGIAllocationAddition(en, newLine.getPSOFGI().getFgiid()
                                    , (newLine.getPSOQty()-currentLine.getPSOQty()));
                        } else if(newLine.getPSOQty() < currentLine.getPSOQty()){
                            im.doFGIAllocationSubtraction(en, newLine.getPSOFGI().getFgiid()
                                    , (currentLine.getPSOQty() - newLine.getPSOQty()));
                        } 
                    }
                }
            }
        }
        
        //Now check for deletes.
        for(final PSOLines currentLine : currentLines){
            boolean found = false;
            for(final PSOLines newLine : newLines){
                if(newLine.getPSOID() == currentLine.getPSOID()){
                    found = true;
                }
            }
            if(!found){
                im.doFGIAllocationSubtraction(en, currentLine.getPSOFGI().getFgiid()
                        , currentLine.getPSOQty());
            }
        }
    }
    
    /***************************************************************************
     * Supply Allocation Update Per Pending SO
     * @param en
     * @param newPSO
     **************************************************************************/
    public void supplyAllocationUpdatePerPSO(final EntityManager en, final PendingSO newPSO){
        final PendingSO currentPSO = getPSOFromID(en, newPSO.getPsoid());
        final InventoryModifiers im = new InventoryModifiers();
        
        //Set lists so there are no null values.
        List<InvPSOLines> currentLines = new ArrayList<InvPSOLines>();
        List<InvPSOLines> newLines = new ArrayList<InvPSOLines>();
        if(currentPSO.getInvPSOLinesCollection()!=null){
            currentLines = currentPSO.getInvPSOLinesCollection();
        }
        if(newPSO.getInvPSOLinesCollection()!=null){
            newLines = newPSO.getInvPSOLinesCollection();
        }
        
        for(final InvPSOLines newLine : newLines){
            if(newLine.getInvPSOID()==null || newLine.getInvPSOID()==0){
                //This is a new line update allocations accordingly.
                im.doSupplyAllocationAddition(en, newLine.getInvPSOSupplyID().getSupID()
                        , newLine.getInvPSOQty());
            } else {
                for(final InvPSOLines currentLine : currentLines){
                    if(newLine.getInvPSOID()==currentLine.getInvPSOID()){
                        if(newLine.getInvPSOQty() > currentLine.getInvPSOQty()){
                            im.doSupplyAllocationAddition(en, newLine.getInvPSOSupplyID().getSupID()
                                    , (newLine.getInvPSOQty()-currentLine.getInvPSOQty()));
                        } else if(newLine.getInvPSOQty() < currentLine.getInvPSOQty()){
                            im.doSupplyAllocationSubtraction(en, newLine.getInvPSOSupplyID().getSupID()
                                    , (currentLine.getInvPSOQty() - newLine.getInvPSOQty()));
                        } 
                    }
                }
            }
        }
        
        //Now check for deletes.
        for(final InvPSOLines currentLine : currentLines){
            boolean found = false;
            for(final InvPSOLines newLine : newLines){
                if(newLine.getInvPSOID() == currentLine.getInvPSOID()){
                    found = true;
                }
            }
            if(!found){
                im.doSupplyAllocationSubtraction(en, currentLine.getInvPSOSupplyID().getSupID()
                        , currentLine.getInvPSOQty());
            }
        }
    }
    
    /***************************************************************************
     * Database access Functions.
     **************************************************************************/
    private PendingSO getPSOFromID(final EntityManager en, final int psoID){
        TypedQuery<PendingSO> query = en.createQuery(
                "SELECT p FROM PendingSO p WHERE p.psoid = ?1", PendingSO.class);
        query.setParameter(1, psoID);
        PendingSO pso = query.getSingleResult();
        return pso;
    }
}
